package com.lcz.manage.forkjoin;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

import com.google.common.collect.Lists;
import com.lcz.manage.util.exception.CCException;

import lombok.extern.slf4j.Slf4j;

/**
 * ForkJoin test
 *
 * @author lucz@yunrong.cn
 * @version V3.0
 * @date 2021/11/19 14:35
 */
@Slf4j
public class ForkJoinTest3 {

    @Test
    public void test() {

        List<String> businessLineList = Arrays.asList("010", "020", "030", "040");
        List<String> overduePhaseList = Arrays.asList("001", "002", "003", "004", "005", "006", "007");

        CCException bizEx;
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        try {
            ForkJoinTask<String> submit = forkJoinPool.submit(
                new RepayUnRefundTask(overduePhaseList, businessLineList));
            String result = submit.get();

            TimeUnit.SECONDS.sleep(10);
            bizEx = StringUtils.equals(result, "success") ? null : new CCException("回款未回退任务执行失败");
        } catch (Exception ex) {
            if(ex instanceof CCException){
                throw (CCException)ex;
            }
            log.error("submit repay unRefund task fail,errMsg={}", ex.getMessage());
            bizEx = new CCException("提交还款未回退任务失败");
        } finally {
            forkJoinPool.shutdown();
        }
        if(null != bizEx){
            throw bizEx;
        }
    }

    public static class RepayUnRefundTask extends RecursiveTask<String> {

        private List<String> overduePhaseList;

        private List<String> businessLineList;


        public RepayUnRefundTask(List<String> overduePhaseList, List<String> businessLineList) {
            this.overduePhaseList = overduePhaseList;
            this.businessLineList = businessLineList;
        }

        @Override
        protected String compute() {

            if (overduePhaseList.size() == 1 && businessLineList.size() == 1) {
                return doStartRepayUnRefundTask(businessLineList.get(0), overduePhaseList.get(0));
            }

            return doSeparateTask(this.overduePhaseList, this.businessLineList);
        }

        private String doStartRepayUnRefundTask(String businessCode, String overduePhaseCode) {

            try {
                log.info("业务...业务条线：{}，逾期阶段：{}", businessCode, overduePhaseCode);

                return "success";
            } catch (Exception ex) {
                throw new CCException("执行还款未回退任务失败");
            }
        }

        private String doSeparateTask(List<String> overduePhaseList, List<String> businessLineList) {

            if (overduePhaseList.size() > 1) {
                int size = overduePhaseList.size();
                int middle = size / 2;

                RepayUnRefundTask repayUnRefundTask = new RepayUnRefundTask(overduePhaseList
                    .subList(0, middle), businessLineList);
                repayUnRefundTask.fork();

                RepayUnRefundTask repayUnRefundTask2 = new RepayUnRefundTask(overduePhaseList
                    .subList(middle, overduePhaseList.size()), businessLineList);
                repayUnRefundTask2.fork();
                return "success";
            }

            int businessMiddle = businessLineList.size() / 2;

            RepayUnRefundTask repayUnRefundTask = new RepayUnRefundTask(overduePhaseList, businessLineList
                .subList(0, businessMiddle));
            repayUnRefundTask.fork();

            RepayUnRefundTask repayUnRefundTask2 = new RepayUnRefundTask(overduePhaseList, businessLineList
                .subList(businessMiddle, businessLineList.size()));
            repayUnRefundTask2.fork();

            String join1 = repayUnRefundTask.join();

            String join2 = repayUnRefundTask2.join();

            if (StringUtils.equals(join1, "fail") || StringUtils.equals(join2,
                "fail")) {
                return "fail";
            }

            return "success";
        }
    }

}
